
#include	<stdio.h>
#include	<stdlib.h>
#include	<time.h>
#include	<unistd.h>
#include	<sys/stat.h>
#include	<signal.h>
#include	<errno.h>
#include    <zlib.h>

#include	"wbsinker_error.hpp"

#include	"storage.hpp"


////////////////////////////////////////////////////////////////////////

int
ISinkStorage::mkpdir ( const char* pszPath )
{
	if (NULL == pszPath)
	{
		return	0;
	}
	
	char	szPath [ 1024 ];
	const char*	p = pszPath;
	
	memset ( szPath, 0, sizeof(szPath) );
	
	while (*p)
	{
		if ('/' == *p)
		{
			if (pszPath == p)
			{
				// root dir
				// skip it
				++p;
				continue;
			}
		
			strncpy ( szPath, pszPath, p - pszPath );
			if (0 == ::access( szPath, F_OK))
			{
				// directory or file exists
				++p;
				continue;
			}
			
			// directory doesNOT exists
			int	iReturn = ::mkdir ( szPath, 0777 );
			if (iReturn < 0)
			{
				ERROR ( CAT_SINKER, 0, "Fail to mkdir '%s' for path '%s' : %s", szPath, pszPath, strerror(errno) );
				return	-1;
			}
		}
		
		++p;
	}
	
	if (0 != ::access( pszPath, F_OK))
	{
		// directory doesNOT exists
		int	iReturn = ::mkdir ( pszPath, 0777 );
		if (iReturn < 0)
		{
			ERROR ( CAT_SINKER, 0, "Fail to mkdir '%s' : %s", pszPath, strerror(errno) );
			return	-1;
		}
	}
	
	return	0;
}

////////////////////////////////////////////////////////////////////////

const char*	
ISinkStorage::getDateString ( void )
{
	static	char	m_szTimeBuf[ 64 ];
	time_t	now = time(NULL);
	
	memset( m_szTimeBuf, 0, sizeof(m_szTimeBuf) );
	struct tm*  pTM = localtime( &now );
	snprintf ( m_szTimeBuf, sizeof(m_szTimeBuf) - 1, "%04d-%02d-%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, pTM->tm_mday );
	
	return	m_szTimeBuf;
}

const char*	
ISinkStorage::getDateTimeString ( void )
{
	static	char	m_szTimeBuf[ 64 ];
	time_t	now = time(NULL);
	
	memset( m_szTimeBuf, 0, sizeof(m_szTimeBuf) );
	struct tm*  pTM = localtime( &now );
	snprintf ( m_szTimeBuf, sizeof(m_szTimeBuf) - 1, "%04d-%02d-%02d %02d:%02d:%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec );
	
	return	m_szTimeBuf;
}

const char*	
ISinkStorage::getCompactDateString ( void )
{
	static	char	m_szTimeBuf[ 64 ];
	time_t	now = time(NULL);
	
	memset( m_szTimeBuf, 0, sizeof(m_szTimeBuf) );
	struct tm*  pTM = localtime( &now );
	snprintf ( m_szTimeBuf, sizeof(m_szTimeBuf) - 1, "%04d%02d%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, pTM->tm_mday );
	
	return	m_szTimeBuf;
}

const char*	
ISinkStorage::getCompactDateTimeString ( void )
{
	static	char	m_szTimeBuf[ 64 ];
	time_t	now = time(NULL);
	
	memset( m_szTimeBuf, 0, sizeof(m_szTimeBuf) );
	struct tm*  pTM = localtime( &now );
	snprintf ( m_szTimeBuf, sizeof(m_szTimeBuf) - 1, "%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900, pTM->tm_mon + 1, pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec );
	
	return	m_szTimeBuf;
}

const char*
ISinkStorage::date ( const char* pszFormat, int iFlags )
{
	static	char	s_szTimeBuf[ 128 ];
	memset( s_szTimeBuf, 0, sizeof(s_szTimeBuf) );
	if ( NULL == pszFormat ) {
		return	s_szTimeBuf;
	}

	time_t	now = time(NULL);
	struct tm*  pTM = localtime( &now );

	char*	pszBuf = s_szTimeBuf;
	int		iLeft = sizeof(s_szTimeBuf) - 1;
	
	bool	bOverflow = false;
	for ( const char* p = pszFormat; ('\0' != *p) && (false == bOverflow); p++ ) {
		switch ( *p ) {
		case	'Y'	:
			iLeft -= 4;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%04d", pTM->tm_year + 1900 );
				pszBuf += 4;
			} 
			break;
		case	'm'	:
			iLeft -= 2;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%02d", pTM->tm_mon + 1 );
				pszBuf += 2;
			} 
			break;
		case	'd'	:
			iLeft -= 2;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%02d", pTM->tm_mday );
				pszBuf += 2;
			} 
			break;
		case	'H'	:
			iLeft -= 2;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%02d", pTM->tm_hour );
				pszBuf += 2;
			} 
			break;
		case	'M'	:
			iLeft -= 2;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%02d", pTM->tm_min );
				pszBuf += 2;
			} 
			break;
		case	'S'	:
			iLeft -= 2;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				sprintf( pszBuf, "%02d", pTM->tm_sec );
				pszBuf += 2;
			} 
			break;
		default	:
			--iLeft;
			if ( iLeft < 0 ) {
				bOverflow = true;
			}
			else {
				*pszBuf = *p;
				++pszBuf;
			} 
			break;
		}	
	}
	
	return	s_szTimeBuf;
}


static	int		_sg_minor_serial = 0;

int
ISinkStorage::getMinorSerial( void )
{
	if ( _sg_minor_serial >= 999 ) {
		_sg_minor_serial = 0;
	}

	++_sg_minor_serial;
	return	_sg_minor_serial;
}


////////////////////////////////////////////////////////////////////////

int 
ISinkStorage::gz_compress (const char* pszFileInput, const char* pszFileOutput)
{
    int     iResultCode = 0;

    FILE*   fileA = fopen(pszFileInput,"rb");
    if (NULL == fileA) {
        iResultCode = -3;
        return  0;
    }

    gzFile  fileB = gzopen(pszFileOutput, "wb");
    if ( NULL == fileB ) {
        iResultCode = -5;
        fclose(fileA);
        return  0;
    }

    char    szBuf[1024];
    while(true) {
        int iReturn = fread(szBuf, 1, sizeof(szBuf), fileA);
        if (iReturn < 1) {
            if (iReturn < 0) {
                iResultCode = -7;
            }
            break;
        }

        int igzReturn = gzwrite(fileB, szBuf, iReturn);
        if (igzReturn != iReturn) {
            iResultCode = -9;
            break;
        }
    }

    gzclose(fileB);
    fclose(fileA);

    return  iResultCode;
}

////////////////////////////////////////////////////////////////////////

